#ifndef AFCORE_COMMON_ALGORITHM_CIRCULAR_QUEUE_
#define AFCORE_COMMON_ALGORITHM_CIRCULAR_QUEUE_

#include <vector>

#include "report.h"

namespace afcore {

/// @brief  循环队列
template<typename T>
class CCircularQueue {
public:
  using RValueType = T;

  /// @brief  构造函数 默认移除
  CCircularQueue() = default;
  /// @brief  构造函数 显示
  /// @param  capacity    最大容量
  /// @note   预留一个空间判断是否已满
  explicit CCircularQueue(size_t capacity)
    : capacity_(capacity + 1)
    , v_(capacity_) {
  }

  /// @brief  拷贝构造函数 默认
  CCircularQueue(const CCircularQueue&) = default;
  /// @brief  拷贝赋值函数 默认
  CCircularQueue& operator=(const CCircularQueue&) = default;

  /// @brief  移动构造函数
  /// @param  [out]   that    循环队列
  CCircularQueue(CCircularQueue&& that) noexcept {
    CopyMoveable(std::move(that));
  }
  /// @brief  移动赋值函数
  /// @param  [out]   that    循环队列
  /// @return 构造好的对象
  CCircularQueue& operator=(CCircularQueue&& that) noexcept {
    if (this != &that) {
      CopyMoveable(std::move(that));
    }
    return *this;
  }

  /// @brief  入队 队尾
  /// @param  item    元素
  void EnQueue(T&& item) {
    DBG_ASSERT(capacity_ > 0);
    v_[tail_] = std::move(item);
    tail_ = (tail_ + 1) % capacity_;

    if (tail_ == head_) {
      head_ = (head_ + 1) % capacity_;
      ++overrun_counter_;
    }
  }

  /// @brief  出队 队头
  /// @note   使用者需要保证队伍中有元素否则中断
  void DeQueue() {
    DBG_ASSERT(!Empty());
    head_ = (head_ + 1) % capacity_;
  }

  /// @brief  队列实际长度
  /// @return 队列实际长度
  size_t Size() const {
    if (tail_ >= head_) {
      return tail_ - head_;
    } else {
      return capacity_ - (head_ - tail_);
    }
  }

  /// @brief  获取i位置的元素
  /// @param  i       队列中的位置
  /// @return i位置的元素
  /// @note   使用者需要保证i的范围不要越界
  const T& At(size_t i) const {
    DBG_ASSERT(i < Size());
    return v_[(head_ + i) % capacity_];
  }

  /// @brief  判断队列是否为空
  /// @return true 队伍为空<br>
  ///         false 队伍不为空
  bool Empty() const {
    return tail_ == head_;
  }

  /// @brief  判断队列是否为满
  /// @return true 队伍为满<br>
  ///         false 队伍不为满
  bool Full() const {
    if (capacity_ > 0) {
      return ((tail_ + 1) % capacity_) == head_;
    }
    return false;
  }

  /// @brief  获取队头元素
  /// @return 获取const类型元素引用
  const T& Front() const {
    DBG_ASSERT(capacity_ > 0);
    return v_[head_];
  }

  /// @brief  获取队头元素
  /// @return 获取非const类型元素引用
  T& Front() {
    DBG_ASSERT(capacity_ > 0);
    return v_[head_];
  }

  /// @brief  获取队伍元素
  /// @return 获取const类型元素引用
  const T& Rear() const {
    DBG_ASSERT(capacity_ > 0);
    return v_[(tail_ + (capacity_ - 1)) % capacity_];
  }

  /// @brief  获取队尾元素
  /// @return 获取const类型元素引用
  T& Rear() {
    DBG_ASSERT(capacity_ > 0);
    return v_[(tail_ + (capacity_ - 1)) % capacity_];
  }

  /// @brief  获取当前累计越界的数量
  /// @return 当前累计越界的数量
  size_t GetOverrunCount() const { return overrun_counter_; }

private:
  /// @brief  拷贝移动 内用
  /// @param  [out]   that    循环队列
  void CopyMoveable(CCircularQueue&& that) noexcept {
    capacity_ = that.capacity_;
    head_ = that.head_;
    tail_ = that.tail_;
    overrun_counter_ = that.overrun_counter_;
    v_ = std::move(that.v_);

    that.capacity_ = 0;
    that.head_ = that.tail_ = 0;
    that.overrun_counter_ = 0;
  }
private:
  size_t capacity_ {0};                         ///< 容量
  typename std::vector<T>::size_type head_ {0}; ///< 队头
  typename std::vector<T>::size_type tail_ {0}; ///< 队尾
  size_t overrun_counter_ {0};                  ///< 越界计数
  std::vector<T> v_;                            ///< 容器
};

} // !namespace afcore

#endif //! AFCORE_COMMON_ALGORITHM_CIRCULAR_QUEUE_
